﻿using System;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Core;

namespace zijian666.Converts.Extensions;
/// <summary>
/// 转换设置扩展方法
/// </summary>
public static class ConvertSettingsExtensions
{
    /// <summary>
    /// 合并2个选项
    /// </summary>
    public static IConvertSettings Merge(this IConvertSettings? settings1, IConvertSettings? settings2)
    {
        if (settings1 is null)
        {
            return settings2 ?? Converts.Settings;
        }
        if (settings2 is null || settings1.Equals(settings2))
        {
            return settings1;
        }
        if (settings1 is MergeConvertSettings agg1 && agg1.Contains(settings2))
        {
            return settings1;
        }
        if (settings2 is MergeConvertSettings agg2 && agg2.Contains(settings1))
        {
            return settings1;
        }
        return new MergeConvertSettings(settings1, settings2);
    }

    /// <summary>
    /// 使用 <seealso cref="IConvertSettings.GetToStringArgument(Type)"/> 获取的参数，将对象转字符串
    /// </summary>
    public static string Format(this IConvertSettings settings, IFormattable input!!)
    {
        var p = settings.GetToStringArgument(input.GetType());
        if (p is null)
        {
            return input switch
            {
                DateTime dt => dt.ToString("yyyy-MM-dd HH:mm:ss"),
                TimeSpan ts => ts.ToString(@"hh\:mm\:ss"),
                DateTimeOffset dto => dto.ToString("yyyy-MM-dd HH:mm:ss"),
                _ => input.ToString(null, null),
            };
        }
        return input.ToString(p.Value.FormatString, p.Value.FormatProvider);
    }

    /// <summary>
    /// 使用 <seealso cref="IConvertSettings.GetToStringArgument(Type)"/> 获取的参数，将对象转字符串
    /// </summary>
    public static string Format(this IConvertSettings settings, IConvertible input)
    {
        var p = settings.GetToStringArgument(input.GetType());
        if (p is null)
        {
            return input switch
            {
                DateTime dt => dt.ToString("yyyy-MM-dd HH:mm:ss"),
                _ => input.ToString(null),
            };
        }
        return input.ToString(p.Value.FormatProvider);
    }

    /// <summary>
    /// 获取资源字符串
    /// </summary>
    /// <param name="settings">转换设置</param>
    public static ResourceStrings GetResourceStrings(this IConvertSettings settings)
        => ResourceStringManager.GetResource(settings?.CultureInfo);

    /// <summary>
    /// 尝试根据设置创建指定类型的实例
    /// </summary>
    /// <typeparam name="T">待创建实例的类型</typeparam>
    /// <param name="settings">转换设置</param>
    public static T CreateInstance<T>(this IConvertSettings settings)
    {
        var compiler = settings?.ReflectCompiler;
        if (compiler is null)
        {
            return Activator.CreateInstance<T>();
        }
        var constructor = typeof(T).GetConstructor(Type.EmptyTypes);
        if (constructor is null)
        {
            return Activator.CreateInstance<T>();
        }
        var creator = compiler.CompileCreator<T>(constructor);
        return creator();
    }

    /// <summary>
    /// 尝试根据设置创建指定类型的实例
    /// </summary>
    /// <param name="settings">转换设置</param>
    /// <param name="type">待创建实例的类型</param>
    /// <returns></returns>
    public static object CreateInstance(this IConvertSettings settings, Type type)
    {
        var compiler = settings?.ReflectCompiler;
        if (compiler is null)
        {
            return Activator.CreateInstance(type);
        }
        var constructor = type.GetConstructor(Type.EmptyTypes);
        if (constructor is null)
        {
            return Activator.CreateInstance(type);
        }
        var creator = compiler.CompileCreator<object>(constructor);
        return creator();
    }
    /// <summary>
    /// 默认字符串分割参数
    /// </summary>
    private static readonly string[] _defaultStringSeparator = { "," };
    /// <summary>
    /// 根据参数设置分割字符串
    /// </summary>
    public static string[] Split(this IConvertSettings? settings, string input) 
        => input.Split(settings?.StringSeparator ?? _defaultStringSeparator, settings?.StringSplitOptions ?? StringSplitOptions.RemoveEmptyEntries);

}
